<template>  
    <div class="ebook-reader">
        <div id="read">

        </div>
    </div>
</template>

<script>
// import { mapGetters } from 'vuex' 不需要这样反复写了，直接混入mixin
import {ebookMixin} from '../../utils/mixin'
import Epub from 'epubjs'
import { getFontSize, saveFontSize, getFontFamily, saveFontFamily,getTheme,saveTheme,getLocation} from '../../utils/localStorage'
// global.ePub = Epub//这行代码的含义是指在全局对象中添加一个epub属性，这个属性的值为Epub模块，这样做的目的是epubjs库中会直接从global中获取epub，如果不加会抛异常，在新版本的epubjs中已经修复这个问题了
import { flatten } from '../../utils/book'
export default {
    mixins: [ebookMixin],
    methods: {
        prevPage() {//进入上一页
            if(this.rendition) {  //如果渲染样式初始化好了
                this.rendition.prev()
            }
        },
        nextPage() { //进入下一页
            if(this.rendition) { 
                this.rendition.next()
            }
        },
        toggleTitleAndMenu() { //点击隐藏标题和菜单
            if(this.menuVisible) {  //如果点击时菜单是看得见的，点击屏幕后隐藏设置
                this.setSettingVisible(-1)
            }
            this.setMenuVisible(!this.menuVisible)
            this.setFontFamilyVisible(false)
        },
        initGesture() { //初始化手势操作
            this.rendition.on('touchstart',event => { //监听事件有两个办法，另一个是document.addEventListener('touchstart',*****)
            //    console.log(event)//查看点击事件中都有什么可以调用
                this.touchStartX = event.changedTouches[0].clientX //取第一只手点击的屏幕X轴位置
                this.touchStartTime = event.timeStamp//点击事件发生时的时间戳
            })
            //touchend 监听触摸结束事件
            this.rendition.on('touchend',event => {
               const offestX = event.changedTouches[0].clientX - this.touchStartX//离开时坐标减去起始位置坐标
               const time = event.timeStamp - this.touchStartTime //移动操作所花费时间
            //    console.log(offestX,time)
               if(time < 500 && offestX > 40) { //如果滑动时间小于0.5秒，并且移动距离大于40，进入上一页
                   this.prevPage()
               } else if(time < 500 && offestX < -40) { //如果滑动时间小于0.5秒，并且移动距离小于-40，进入下一页
                   this.nextPage() 
               } else { //不满足上述两个条件，显示或隐藏屏幕标题栏和菜单栏（显示时隐藏，隐藏时显示）
                   this.toggleTitleAndMenu()
               }
            //    console.log(event)
            /* Event 接口的 preventDefault()方法，告诉user agent：如果此事件没有被显式处理，
               它默认的动作也不应该照常执行。此事件还是继续传播，除非碰到事件侦听器调用stopPropagation() 
               或stopImmediatePropagation()，才停止传播。*/
                event.preventDefault() //禁止事件默认方法调用
                event.stopPropagation() //禁止事件传播
            })
        },
        initFontSize() {  //初始化字体大小，从LocalStorage中获取
            let fontSize = getFontSize(this.fileName)
            if(!fontSize) { //如果本地没有保存，保存默认大小
                saveFontSize(this.fileName,this.defaultFontSize) //保存默认大小到本地
            } else { 
                this.rendition.themes.fontSize(fontSize + 'px') //更改书籍的字体大小
                this.setDefaultFontSize(fontSize) //更改默认字体大小的值
            }
        },
        initTheme() { //初始化主题
            let defaultTheme = getTheme(this.fileName) //获取本地主题
            if(!defaultTheme) { 
                defaultTheme = this.themeList[0].name 
                saveTheme(this.fileName,defaultTheme)   //保存默认主题
            }
            this.setDefaultTheme(defaultTheme) //设置默认主题
            this.themeList.forEach(theme => { //注册主题
                this.rendition.themes.register(theme.name,theme.style)
            })
            this.rendition.themes.select(defaultTheme)//选择默认主题
        },
        initFontFamily() { //初始化字体
            let font = getFontFamily(this.fileName) //获取本地字体
            if(!font) { //如果本地没有字体，保存默认字体为本地字体
                saveFontFamily(this.fileName,this.defaultFontFamily)
            } else { 
                this.rendition.themes.font(font) //设置电子书字体为本地字体
                this.setDefaultFontFamily(font) //设置默认字体为当前本地字体
            }

        },
        initRendition() { //显示电子书
            this.rendition = this.book.renderTo("read",{   //renderTo表示渲染到哪里,属性有宽高等,
                width: innerWidth,                          //rendition没在data中定义，但好像能通过this直接定义
                height: innerHeight,
                methods: 'default'
            })
            const location = getLocation(this.fileName)
            //下面这一块代码很重要
            // this.rendition.display().then(() => { //如果display不这样单独写出来,手势初始化就会失效，不知道为啥
            //     this.initFontSize()
            //     this.initTheme() //初始化主题
            //     this.initFontFamily() //初始化字体样式
            //     this.initGlobalStyle()   //初始化全局样式,这里是为了让标题和菜单栏颜色跟随主题改变
            //     this.refreshLocation()
            // })
            this.display(location, () => { //统一了display方法，传入了当前的location，显示当前location处内容及获取进度，但是这里进度获取不到，因为BookAvailable是false,得在下方initEpub中获取
                this.initTheme()        //如果location存在就显示location下的初始化
                this.initFontSize()      //如果location不存在就显示null下的初始化
                this.initFontFamily()
                this.initGlobalStyle()
                // this.refreshLocation()
            })
            this.rendition.hooks.content.register(contents => {//往电子书html中header注入字体文件，只能用网络地址，
                Promise.all([
                    contents.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/daysOne.css`),
                    contents.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/cabin.css`),
                    contents.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/montserrat.css`),
                    contents.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/tangerine.css`),
                    // console.log('加载字体中')
                ]).then(() => {
                    // console.log('字体全部加载完毕')
                })
                
            })
        },
        parseBook() { //解析电子书内容
             this.book.loaded.navigation.then(nav => {
                const navItem = flatten(nav.toc)  //navItem是各个级别混合在一起的一维数组目录
                 //通过parent来判断是几级目录，没有parent就是一级目录
                function find(item, level = 0){
                    //没有上一级，返回默认level 0,即是第一级目录,如果有上一级，递归调用find
                    return !item.parent ? level : 
                    //item的上一级刚好能从navItem中过滤出来，则说明
                    //有爸爸，找到爸爸，自己加一，level++,变成第二级
                    //如果爸爸有爸爸，自己再加一，level++，变成第三级,
                    //如果爷爷有爸爸，以此类推，自己变成第四级...
                        find(navItem.filter(parentItem => parentItem.id === item.parent)[0],++level) 
                }
                navItem.forEach(item => {//对每一个章节分别进行级别查询
                    item.level = find(item) //调用上方find函数
                })
                this.setNavigation(navItem)//将分好级的navItem传入到vuex中
            })
        },
        initEpub() { //初始化电子书
            const url = `${process.env.VUE_APP_RES_URL}/epub/` + this.fileName + '.epub' //与环境路径拼接
            this.book = new Epub(url)
            this.setCurrentBook(this.book) //把this.book交给vuex保管,直接通过this调用vuex actions中函数要提前混入mixin
            this.initRendition() //渲染初始化过程
            this.initGesture()//初始化手势操作
            this.parseBook()
            this.book.ready.then(() => {  //加载图书中的所有部分以生成位置，下面只是一个简单的分页算法，并不准确
                return this.book.locations.generate(750 * (window.innerWidth)/375 * (getFontSize(this.fileName)/16))
            }).then(locations => { 
                // console.log(locations)
                this.setBookAvailable(true) //设置进度条可以拖动
                this.refreshLocation()  //不加这一句刷新后就无法让进度条跟随页面变化
            })
        }
    },
    mounted() { 
        const fileName = this.$route.params.fileName.split('|').join('/') //.fileName是因为route中子路径是fileName,
                                                                        //因为自己规定路径设置中有|,得把他替换为/才能获取nginx中文件
        this.$store.dispatch('setFileName',fileName).then(() => { 
            this.initEpub()
        })
    }
};
</script>

<style lang="scss" scoped>

</style>